package com.shisan.tingshu.search.factory;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 定时任务线程池工厂类
 */
public class ScheduleTaskThreadPoolFactory {

    static ScheduledExecutorService scheduledExecutorService = null;

    // 在加载ScheduleTaskThreadPoolFactory类的时候，提前将定时任务的线程池对象创建出来
    static {

        scheduledExecutorService = Executors.newScheduledThreadPool(2);
    }

    /**
     * 使用单例设计模式定义一个工厂类的实例对象（饿汉式。在并发情况下，比懒汉式安全一点）
     * 饿汉式：类加载时就立即初始化单例实例，线程安全但可能造成资源浪费
     * 懒汉式：首次使用时才初始化单例实例，节省资源但需额外处理线程安全问题
     */
    private static ScheduleTaskThreadPoolFactory INSTANCE = new ScheduleTaskThreadPoolFactory();


    /**
     * 获取上面定义的实例对象
     */
    public static ScheduleTaskThreadPoolFactory getINSTANCE() {

        return INSTANCE;
    }


    /**
     * 私有化构造器。让外面无法通过new的方式创建该工厂类的实例对象
     */
    private ScheduleTaskThreadPoolFactory() {

    }

    /**
     * 该方法使得工厂可以接收外部提交过来的任务
     * runnable：外部提交过来的任务
     * ttl：延迟时间
     * timeUnit：时间单位
     */
    public void execute(Runnable runnable, Long ttl, TimeUnit timeUnit) {

        // 一次性延迟任务+嵌套任务本身，进而实现定时的效果（Nacos源码就是这么做的）
        scheduledExecutorService.schedule(runnable, ttl, timeUnit);
    }

    /**
     * 计算时间差
     */
    public Long diffTime(Long currentTime) {

        // 获取当前时间的下一周的凌晨2点的时间戳
        LocalDate localDate = LocalDate.now().plusDays(7);
        LocalDateTime localDateTime = LocalDateTime.of(localDate, LocalTime.of(2, 0, 0));
        // 将LocalDateTime转换为毫秒值。ZoneId.systemDefault()是获取系统默认时区
        long time = localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
        // 当前时间减去下一周的凌晨2点的时间戳，得到时间差（小减大、大减小都行）
        Long diffTime = currentTime - time;
//        Long diffTime =time - currentTime;
        long absDiffTime = Math.abs(diffTime);

        return absDiffTime;
    }
}
